パソコン活用研究PCマニアックの道(アセンブラ、DOS、Windows、旧型PCの活用研究)
FORMAT文 (数値)
=============================================
今回はFortranの格調高きFormat文の数値の書式にについてまとめてみました。
最古のコンピュータ言語であるFORTRANは、紙にパンチされたデータを読み込む時代に
作られた言語であり、そんな時代の取り決めが化石のように残っています。このFORMAT文
というのも、そんな化石のにおいのするもののひとつですが、ちょっばかり古代の味をなめて
みましょう。
=============================================
1 はじめに
FORMAT文は、READ, WRITEなどの入出力文で、入出力の書式を指定する文です。BASICでも
print usingで画面出力やプリンター出力時の書式を制御したり、C言語でもprintf,
scanfでは入出力
の書式を記述しましたが、それらと同様のものです。
実際のプログラムでは、FORMATは入出力命令のREADやWRITEと対になって使用されます。以下
のように、READ,WRITEの命令の中に参照するFORMAT文の文番号が記述されます。
WRITE(6,100)k
100 FORMAT('SUU=', I4)
今回はは数値の書式をまとめてみました。
2 整数の欄記述子 I
(1) 整数の欄記述子の一般的規則
一般的にFORMAT文の( )中に記述する書式を指定する記述を、欄記述子と呼びます。
整数の欄記述子はIです。Iの後ろに欄の幅(ケタ数)を記述します。例えばI3とすると、正負の符号
も含めて3ケタ分が出力(または入力)されます。
複数の変数を入出力する時は、欄記述子をFORMAT文の中に複数記述します。例えば、3ケタ、
4ケタ、5ケタの3つの整数を出力する時は、
FORMAT(I3, I4, I5)
のように書きます。
出力の場合は、欄の幅が余れば左側に空白が挿入
され、欄の幅が足りなければ*が挿入されます(コンパイラにより、先頭だけ*にするものや、全部の
ケタに*を表示するものなど、仕様に違いがある)。
例えば、SalfordのFortran77では以下のようです。( _ は空白をあらわす)
欄記述子 | 値 | 出力 | |||||
I5 | 123 |
|
|||||
I5 | -321 |
|
|||||
I3 | 1234 |
|
欄記述子の前には、その欄記述子を繰り返し使用する回数を記述します。
例えば、3I5 と記述すると5ケタの整数の出力を3回繰り返す、ということになります。(これは、I5,I5,I5
と記述するのと同じことになります)
(2) 入力の時のFORMAT文の注意点
READ文で入力する時にもちょっと厄介なことがあり注意が必要です。あるコンパイラ(MicroSoftの
Fortarn80など)では、先頭(左側)の空白以外の空白はゼロとみなされます。ここがちょっと厄介な
ところです。
(SalfordのFortran77では、先頭以外の空白はリターンキー、あるいは区切り記号と同じにみなされ
るようです)
いずれにしても、コンパイラの仕様を確認しないと、ミスのおこりがちなところです。
入力者にうまく指示しないと、意図しない数値が入力されることになります。また指定した欄の幅
(ケタ数)より入力値が大きいと正しい値が入力されません。例えばI4という指定(符号をあわせて
4ケタ)に対して、-1234と入力すると、最初の4ケタだけが取り込まれて、-123という値が入力
されたことになります。
例えば、以下の通りのようになります。
欄記述子 | 入力欄(_は空白とする) | 入力された値(Fortran80) | 入力された値(Fortran77) | ||||||
I4 |
|
123 | 123 | ||||||
I6 |
|
3210 | 321 | ||||||
I5 |
|
-1020 | -1 | ||||||
I4 |
|
-123 | -123 |
なお、SalfordのFortran77ではREADの時は参照するFORMAT文を指定する必要はなく、
READ(5, *)
のように記述することができます。
FORMAT文を指定すると、入力データの形式が欄記述子の記述に厳密に制約されるので、
SalfordのFortran77のこの仕様はちょっと柔軟性があり便利です。
3 実数の欄記述子
(1) 実数の欄記述子
実数の欄記述子には、F,E,G の3つの型があります。
F型変換
F型変換は、rFw.dの形をとります。rは繰り返しの回数です。wは表示のケタ数を示し、dはそのうち
の小数部分のケタ数を示します。
例えば、F9.4とすると、全体のケタ数が9ケタ、うち小数部分が4ケタで表示されます。
<--- w ---------> | ||||||||
<--d--> | ||||||||
5 | 5 | . | 3 | 1 | 7 | 5 | ||
1 | 2 | 3 | 4 | . | 7 | 5 | 0 | 0 |
F型変換の場合も出力欄の幅が余れば左側に空白が出力され、また小数部の欄が余れば0が
右側に出力されます。小数部の欄が不足すれば、不足した部分は表示されません(切捨てされた
のと同じ表示になる)。
欄記述子 | 数値 | 出力( _ は空白を示す) | |||||||
F6.3 | 4.2 |
|
|||||||
F7.1 | 35.123 |
|
E型変換
E型変換は、rEw.dの形をとります。rは繰り返しの回数です。wは全体の表示ケタ数、dは少数部分の
表示ケタ数を示します。表示は以下のようになるので、w>d+7 である必要があります。
(仮数1と指数部で7ケタ分の表示欄が必要)
<-----w----------> | |||||||||
仮数1 | 仮数2 <-d-> |
指数部 | |||||||
- | _ | . | 2 | 5 | 6 | E | + | 0 | 3 |
G型変換
G型は混合型と呼ばれる型で、データの絶対値の大きさによって、F型で表示したり、E型で表示したりします。
Gw.dの形をとり、wが表示の欄の幅を示し、dはそのうちの小数部分のケタ数を示します。
実際の表示は、出力しようとするデータの絶対値をnとすると、0.1=<n<10dの範囲ではF型として表示し、それ
以外ではE型として表示します。
F型で表示の部分は以下のようになります。
範囲 | 書式 |
---|---|
0.1 =<n < 1.0 | F(w-4).d |
1.0 =<n< 10.0 | F(w-4).(d-1) |
... | ... |
10(d-2) =<n<10(d-1) | F(w-4).1 |
10(d-1) =<n< 10d | F(w-4).0 |
C FORMAT TEST INTEGER I,J REAL*4 A A=0.12345678E-05 DO 1 I = 1,10,1 J=I*10 A=A*10.0 WRITE(5,100) I, J,A, A, A 100 FORMAT(2I4, F20.8, E20.8, G20.8) 1 CONTINUE STOP END |
以下は、上記のプログラムの実行例です。
D:\win95\ftn77#>frmtest 1 10 0.00001235 0.12345678E-04 0.12345678E-04 2 20 0.00012346 0.12345678E-03 0.12345678E-03 3 30 0.00123457 0.12345677E-02 0.12345677E-02 4 40 0.01234568 0.12345677E-01 0.12345677E-01 5 50 0.12345678 0.12345678E+00 0.12345678 6 60 1.23456776 0.12345678E+01 1.2345678 7 70 12.34567738 0.12345677E+02 12.345677 8 80 123.45677185 0.12345677E+03 123.45677 9 90 1234.56774902 0.12345677E+04 1234.5677 10 100 12345.67773438 0.12345678E+05 12345.678 |
(2) 実数の入力の注意点
実数の入力でも、注意すべきルールがあります。例えばF6.2と指定すると、符号、小数点含めて6ケタ、
小数点以下2ケタの指定になります。この時、例えば入力データが123.45のように、小数点を含んで
いれば、このとおり123.45として値がとりこまれます。しかし、入力データが12345のように小数点を
含んでいないと、欄記述子の記述のルールが適用されて、値は123.45として取り込まれてしまいます。
入力データが123.0なら、123.00として取り込まれます。
このように、実数の入力の場合は、以下のような規則に従います。
(A)入力データに小数点があれば、入力データのとおりに取り込む
(B)入力データに小数点がなければ、欄記述子に従って取り込む
整数の欄記述子のところでも書きましたが、SalfordのFortran77では、FORMAT文を指定しない
記述の仕方もできます。実数の入力も、いちいちFORMAT文の指定をしないほうが柔軟性があって
便利だと思います。
SalfordのFortran77で整数と実数の入力の時の動作を確認してみました。不正な値が入った場合の
処理などを確認してみて下さい。
サンプルプログラム pract1
I3(3ケタの整数)、F6.2(6ケタで、小数点以下2ケタの実数)を入力して、そのまま出力するプログラム
です。
C program practice READ(5,100)j,x 100 FORMAT(I3,F6.2) WRITE(6,200)j,x 200 FORMAT('I ',I3, ' F ',F6.2) END |
プログラムの実行例
D:\win95\ftn77#>pract1 1,1.0 I 1 F 1.00 D:\win95\ftn77#>pract1 12,12.34 I 12 F 12.34 D:\win95\ftn77#>pract1 12,123.45 I 12 F 123.45 D:\win95\ftn77#>pract1 1,1 I 1 F 0.01 D:\win95\ftn77#>pract1 12,12 I 12 F 0.12 D:\win95\ftn77#>pract1 123,123.45 I 123 F 0.00 D:\win95\ftn77#>pract1 12345,12.34 I 123 F 0.45 D:\win95\ftn77#>pract1 12,1234.56 I 12 F ****** |
問題ない場合 問題ない場合 問題ない場合 実数に小数点がないデータが入力された場合 欄記述子の書式が適用された。 実数に小数点がないデータが入力された場合 欄記述子の書式が適用された。 I3(符号含めて整数3ケタ)にオーバーした値が入力された 取り込まれた値は不正な値になっている。 I3(符号含めて整数3ケタ)にオーバーした値が入力された 取り込まれた値は不正な値になっている。 実数値にオーバーした値が入力された。 |
このようにREAD文での入力時に、FORMAT文を指定すると、入力データは欄記述子のとおりに
入力しないと、取り込まれた値が不正なものになります。FORTRANでデータを扱う時は、プログラム
設計時に入力データの書式をどうするかよく吟味し、また入力時にデータの書式を正しく守らせる
必要があります。